
using System;
using System.Collections.Generic;
using System.Text;

namespace ScrewTurn.Wiki.PluginFramework {

	/// <summary>
	/// It is the interface that must be implemented in order to create a custom Pages Storage Provider for ScrewTurn Wiki.
	/// </summary>
	/// <remarks>A class that implements this interface <b>should not</b> have any kind of data caching.</remarks>
	public interface IPagesStorageProvider : IStorageProvider {

		/// <summary>
		/// Gets all the Pages.
		/// </summary>
		/// <remarks>The array is unsorted.</remarks>
		PageInfo[] AllPages { get; }

		/// <summary>
		/// Gets all the Categories.
		/// </summary>
		/// <remarks>The array is unsorted.</remarks>
		CategoryInfo[] AllCategories { get; }

		/// <summary>
		/// Adds a Category.
		/// </summary>
		/// <param name="name">The Category name.</param>
		/// <returns>The correct CategoryInfo object.</returns>
		/// <remarks>The moethod should set category's Pages to an empty array.</remarks>
		CategoryInfo AddCategory(string name);

		/// <summary>
		/// Renames a Category.
		/// </summary>
		/// <param name="category">The Category to rename.</param>
		/// <param name="newName">The new Name.</param>
		/// <returns>The correct CategoryInfo object.</returns>
		CategoryInfo RenameCategory(CategoryInfo category, string newName);

		/// <summary>
		/// Removes a Category.
		/// </summary>
		/// <param name="category">The Category to remove.</param>
		/// <returns>True if the Category has been removed successfully.</returns>
		bool RemoveCategory(CategoryInfo category);

		/// <summary>
		/// Merges two Categories.
		/// </summary>
		/// <param name="source">The source Category.</param>
		/// <param name="destination">The destination Category.</param>
		/// <returns>The correct CategoryInfo object.</returns>
		/// <remarks>The <b>destination</b> Category remains, while the <b>source</b> Category is deleted, and all its Pages re-binded in the <b>destination</b> Category.</remarks>
		CategoryInfo MergeCategories(CategoryInfo source, CategoryInfo destination);

		/// <summary>
		/// Gets the Content of a Page.
		/// </summary>
		/// <param name="page">The Page.</param>
		/// <returns>The Page Content object.</returns>
		PageContent GetContent(PageInfo page);

		/// <summary>
		/// Gets the Backup/Revision numbers of a Page.
		/// </summary>
		/// <param name="page">The Page to get the Backups of.</param>
		/// <returns>The Backup/Revision numbers.</returns>
		List<int> GetBackups(PageInfo page);

		/// <summary>
		/// Gets the Content of a Backup of a Page.
		/// </summary>
		/// <param name="page">The Page to get the backup of.</param>
		/// <param name="revision">The Backup/Revision number.</param>
		/// <returns>The Page Backup.</returns>
		PageContent GetBackupContent(PageInfo page, int revision);

		/// <summary>
		/// Forces to overwrite or create a Backup.
		/// </summary>
		/// <param name="content">The Backup content.</param>
		/// <param name="revision">The revision.</param>
		/// <returns>True if the Backup has been created successfully.</returns>
		bool SetBackupContent(PageContent content, int revision);

		/// <summary>
		/// Backups a Page.
		/// </summary>
		/// <param name="page">The Page to backup.</param>
		/// <returns>True if the Page has been backupped successfully.</returns>
		bool Backup(PageInfo page);

		/// <summary>
		/// Adds a Page.
		/// </summary>
		/// <param name="name">The Page Name.</param>
		/// <param name="creationDateTime">The creation Date/Time.</param>
		/// <returns>The correct PageInfo object or null.</returns>
		/// <remarks>This method should <b>not</b> create the content of the Page.</remarks>
		PageInfo AddPage(string name, DateTime creationDateTime);

		/// <summary>
		/// Renames a Page.
		/// </summary>
		/// <param name="page">The Page to rename.</param>
		/// <param name="newName">The new Name.</param>
		/// <returns>The correct PageInfo object.</returns>
		PageInfo RenamePage(PageInfo page, string newName);

		/// <summary>
		/// Sets the status of a Page.
		/// </summary>
		/// <param name="page">The Page.</param>
		/// <param name="status">The Status.</param>
		/// <returns>The correct PageInfo object.</returns>
		PageInfo SetStatus(PageInfo page, PageStatus status);

		/// <summary>
		/// Modifies the Content of a Page.
		/// </summary>
		/// <param name="page">The Page.</param>
		/// <param name="title">The Title of the Page.</param>
		/// <param name="username">The Username.</param>
		/// <param name="dateTime">The Date/Time.</param>
		/// <param name="comment">The Comment of the editor, about this revision.</param>
		/// <param name="content">The Page Content.</param>
		/// <param name="backup">A value specifying whether or not to create a backup of the Page.</param>
		/// <returns>True if the Page has been modified successfully.</returns>
		/// <remarks>If the Page does not exist, the method creates it and returns false.</remarks>
		bool ModifyPage(PageInfo page, string title, string username, DateTime dateTime, string comment, string content, bool backup);

		/// <summary>
		/// Performs the rollback of a Page to a specified revision.
		/// </summary>
		/// <param name="page">The Page to rollback.</param>
		/// <param name="revision">The Revision to rollback the Page to.</param>
		/// <returns>True if the roolback succeeded.</returns>
		bool RollbackPage(PageInfo page, int revision);

		/// <summary>
		/// Deletes the Backups of a Page, up to a specified revision.
		/// </summary>
		/// <param name="page">The Page to delete the backups of.</param>
		/// <param name="revision">The newest revision to delete (newer revision are kept) or -1 to delete all the Backups.</param>
		/// <returns>True if the deletion succeeded.</returns>
		bool DeleteBackups(PageInfo page, int revision);

		/// <summary>
		/// Removes a Page.
		/// </summary>
		/// <param name="page">The Page to remove.</param>
		/// <returns>True if the Page is removed successfully.</returns>
		bool RemovePage(PageInfo page);

		/// <summary>
		/// Binds a Page with one or more Categories.
		/// </summary>
		/// <param name="page">The Page to bind.</param>
		/// <param name="categories">The Categories to bind the Page with.</param>
		/// <returns>True if the binding succeeded.</returns>
		/// <remarks>After a successful operation, the Page is binded with all and only the categories passed as argument.</remarks>
		bool Rebind(PageInfo page, string[] categories);

		/// <summary>
		/// Gets the Page Messages.
		/// </summary>
		/// <param name="page">The Page.</param>
		/// <returns>The list of the <b>first-level</b> Messages, containing the replies properly nested.</returns>
		Message[] GetMessages(PageInfo page);

		/// <summary>
		/// Gets the total number of Messages in a Page Discussion.
		/// </summary>
		/// <param name="page">The Page.</param>
		/// <returns>The number of messages.</returns>
		int GetMessageCount(PageInfo page);

		/// <summary>
		/// Adds a new Message to a Page.
		/// </summary>
		/// <param name="page">The Page.</param>
		/// <param name="username">The Username.</param>
		/// <param name="subject">The Subject.</param>
		/// <param name="dateTime">The Date/Time.</param>
		/// <param name="body">The Body.</param>
		/// <param name="parent">The Parent Message ID, or -1.</param>
		/// <returns>True if the Message is added successfully.</returns>
		bool AddMessage(PageInfo page, string username, string subject, DateTime dateTime, string body, int parent);

		/// <summary>
		/// Removes a Message.
		/// </summary>
		/// <param name="page">The Page.</param>
		/// <param name="id">The ID of the Message to remove.</param>
		/// <param name="removeReplies">A value specifying whether or not to remove the replies.</param>
		/// <returns>True if the Message is removed successfully.</returns>
		bool RemoveMessage(PageInfo page, int id, bool removeReplies);

		/// <summary>
		/// Modifies a Message.
		/// </summary>
		/// <param name="page">The Page.</param>
		/// <param name="id">The ID of the Message to modify.</param>
		/// <param name="username">The Username.</param>
		/// <param name="subject">The Subject.</param>
		/// <param name="dateTime">The Date/Time.</param>
		/// <param name="body">The Body.</param>
		/// <returns>True if the Message is modified successfully.</returns>
		bool ModifyMessage(PageInfo page, int id, string username, string subject, DateTime dateTime, string body);

		/// <summary>
		/// Gets all the Navigation Paths.
		/// </summary>
		/// <remarks>The array is unsorted.</remarks>
		NavigationPath[] AllNavigationPaths { get; }

		/// <summary>
		/// Adds a new Navigation Path.
		/// </summary>
		/// <param name="name">The Name of the Path.</param>
		/// <param name="pages">The Pages array.</param>
		/// <returns>The correct NavigationPath object.</returns>
		NavigationPath AddNavigationPath(string name, PageInfo[] pages);

		/// <summary>
		/// Modifies an existing Navigation Path.
		/// </summary>
		/// <param name="name">The Name of the Path to modify.</param>
		/// <param name="pages">The Pages array.</param>
		/// <returns>The correct NavigatinPath object.</returns>
		NavigationPath ModifyNavigationPath(string name, PageInfo[] pages);

		/// <summary>
		/// Removes a Navigation Path.
		/// </summary>
		/// <param name="name">The Name of the Path to remove.</param>
		/// <returns>True if the Path is removed successfully.</returns>
		bool RemoveNavigationPath(string name);

		/// <summary>
		/// Gets all the Snippets.
		/// </summary>
		Snippet[] AllSnippets { get; }

		/// <summary>
		/// Adds a new Snippet.
		/// </summary>
		/// <param name="name">The Name of the Snippet.</param>
		/// <param name="content">The Content of the Snippet.</param>
		/// <returns>The correct Snippet object.</returns>
		Snippet AddSnippet(string name, string content);

		/// <summary>
		/// Modifies a new Snippet.
		/// </summary>
		/// <param name="name">The Name of the Snippet to modify.</param>
		/// <param name="content">The Content of the Snippet.</param>
		/// <returns>The correct Snippet object.</returns>
		Snippet ModifySnippet(string name, string content);

		/// <summary>
		/// Removes a new Snippet.
		/// </summary>
		/// <param name="name">The Name of the Snippet to remove.</param>
		/// <returns>True if the Snippet is removed successfully.</returns>
		bool RemoveSnippet(string name);

	}

}
